package cn.com.libertymutual.core.exception;

import org.hibernate.CallbackException;
import org.hibernate.HibernateException;
import org.hibernate.JDBCException;
import org.hibernate.NonUniqueResultException;
import org.hibernate.PersistentObjectException;
import org.hibernate.PropertyAccessException;
import org.hibernate.PropertyValueException;
import org.hibernate.QueryException;
import org.hibernate.SessionException;
import org.hibernate.TransactionException;
import org.hibernate.dialect.lock.LockingStrategyException;
import org.hibernate.jdbc.BatchFailedException;
import org.hibernate.loader.custom.NonUniqueDiscoveredSqlAliasException;
import org.hibernate.service.spi.ServiceException;

import com.google.common.base.Strings;


/**
 * 	数据库的错误
 * 
 *  @author 2016-05-23 14:22 zhaoyu
 *
 *
 *	@version 1.0
 */

public class CustomJDBCException extends RuntimeException {

	
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 3221050542959990499L;
	private int errorCode = 9996;
	private String errorMessage;
	
	//添加枚举类型的属性  author:tracy.liao date:2016-4-27
	private ExceptionEnums exceptionEnums;
	
	public CustomJDBCException() {
		super();
	}
	
	public CustomJDBCException( Throwable e ) {
		//如果是他自己
		if(e instanceof CustomJDBCException){
			this.errorCode = ((CustomJDBCException) e).getErrorCode();
			this.errorMessage = ((CustomJDBCException) e).getErrorMessage();
		//实体被锁定
		}else if(e instanceof LockingStrategyException){
			this.errorCode = HibernateExceptionEnums.LOCKING_STRATEGY_EXCEPTION_KEY.getCode();
			this.errorMessage =  HibernateExceptionEnums.LOCKING_STRATEGY_EXCEPTION_KEY.getMessage();
		//关联查询的两个表有相同的列名
		}else if(e instanceof NonUniqueDiscoveredSqlAliasException){
			this.errorCode = HibernateExceptionEnums.NONUNIQUE_DISCOVERED_SQL_ALIAS_EXCEPTION_KEY.getCode();		
			this.errorMessage =  HibernateExceptionEnums.NONUNIQUE_DISCOVERED_SQL_ALIAS_EXCEPTION_KEY.getMessage();
		//重复的主键
		}else if(e instanceof NonUniqueResultException){
			this.errorCode = HibernateExceptionEnums.NONUNIQUE_RESULT_EXCEPTION_KEY.getCode();
			this.errorMessage =  HibernateExceptionEnums.NONUNIQUE_RESULT_EXCEPTION_KEY.getMessage();
		//某个字段自动生成,无法设置值
		}else if(e instanceof PersistentObjectException){
			this.errorCode = HibernateExceptionEnums.PERSISTENT_OBJECT_EXCEPTION_KEY.getCode();
			this.errorMessage =  HibernateExceptionEnums.PERSISTENT_OBJECT_EXCEPTION_KEY.getMessage();
		//属性和数据关联失败,字段值不合法
		}else if(e instanceof PropertyAccessException||e instanceof PropertyValueException){
			this.errorCode = HibernateExceptionEnums.PROPERTY_ACCESS_OR_VALUE_EXCEPTION_KEY.getCode();
			this.errorMessage =  HibernateExceptionEnums.PROPERTY_ACCESS_OR_VALUE_EXCEPTION_KEY.getMessage();
		//查询语句出错
		}else if(e instanceof QueryException){
			this.errorCode = HibernateExceptionEnums.QUERY_EXCEPTION_KEY.getCode();
			this.errorMessage = HibernateExceptionEnums.QUERY_EXCEPTION_KEY.getMessage();
		//事物提交失败
		}else if(e instanceof BatchFailedException){
			this.errorCode = HibernateExceptionEnums.BATCH_FAILED_EXCEPTION_KEY.getCode();
			this.errorMessage =  HibernateExceptionEnums.BATCH_FAILED_EXCEPTION_KEY.getMessage();
		//回滚事物失败
		}else if(e instanceof CallbackException){
			this.errorCode = HibernateExceptionEnums.CALL_BACK_EXCEPTION_KEY.getCode();
			this.errorMessage =  HibernateExceptionEnums.CALL_BACK_EXCEPTION_KEY.getMessage();
		//jdbc驱动错误或配置异常
		}else if(e instanceof ServiceException){
			this.errorCode = HibernateExceptionEnums.SERVICE_EXCEPTION_KEY.getCode();
			this.errorMessage = HibernateExceptionEnums.SERVICE_EXCEPTION_KEY.getMessage();
		//session异常
		}else if(e instanceof SessionException){
			this.errorCode = HibernateExceptionEnums.SESSION_EXCEPTION_KEY.getCode();
			this.errorMessage =  HibernateExceptionEnums.SESSION_EXCEPTION_KEY.getMessage();
		//开启事物异常
		}else if(e instanceof TransactionException){
			this.errorCode = HibernateExceptionEnums.TRANSACTION_EXCEPTION_KEY.getCode();
			this.errorMessage =  HibernateExceptionEnums.TRANSACTION_EXCEPTION_KEY.getMessage();
		//jdbc异常
		}else if(e instanceof JDBCException){
			//获取数据库错误码
			JDBCException jDBCException = (JDBCException)e;
			this.errorCode = jDBCException.getErrorCode();
			//遍历枚举，与错误代码做比较
			for(DBExceptionEnums dBExceptionEnums:DBExceptionEnums.values()){
				if(errorCode == dBExceptionEnums.getCode()){
					this.errorMessage = dBExceptionEnums.getMessage();
				}
				
			}
		//hibernate其他异常
		}else if(e instanceof HibernateException){
			this.errorCode = HibernateExceptionEnums.HIBERNATE_EXCEPTION_KEY.getCode();
			this.errorMessage =  HibernateExceptionEnums.HIBERNATE_EXCEPTION_KEY.getMessage();
		//根异常。用以描述应用程序希望捕获的情况
		}else{
			this.errorCode = LangExceptionEnums.Exception_KEY.getCode();
			this.errorMessage =  LangExceptionEnums.Exception_KEY.getMessage();
		}
	}
	

	public CustomJDBCException( String message ) {
		super( message );
		errorMessage = message;
	}
	public CustomJDBCException( String message, Throwable e ) {
		super( message, e );
		errorMessage = message;
	}

	public CustomJDBCException( int errorCode, String message ) {
		super(message);
		this.errorCode = errorCode;
		this.errorMessage = message;
	}
	public CustomJDBCException( int errorCode, String message, Throwable e ) {
		super(message, e);
		this.errorCode = errorCode;
		this.errorMessage = message;
	}
	
	/**
	 * 添加枚举类型构造方法
	 * @author tracy.liao
	 * @date 2016-4-27
	 * @param exceptionEnums
	 * @param message
	 */
	public CustomJDBCException(ExceptionEnums exceptionEnums, String message){
		super(message);
		this.exceptionEnums=exceptionEnums;
		this.errorMessage=message;
	}

	/**
	 * @return the exceptionEnums
	 */
	public ExceptionEnums getExceptionEnums() {
		return exceptionEnums;
	}

	/**
	 * @param exceptionEnums the exceptionEnums to set
	 */
	public void setExceptionEnums(ExceptionEnums exceptionEnums) {
		this.exceptionEnums = exceptionEnums;
	}

	public int getErrorCode() {
		return errorCode;
	}
	public String getErrorMessage() {
		return errorMessage;
	}
	
	/**获取错误码和错误信息*/
	public String getErrorCodeAndMessage(){
		return String.format("%d-%s", errorCode, Strings.isNullOrEmpty(errorMessage) ? "系统异常，如果多次出现，请联系管理员" : errorMessage );
	}
	
}
